home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / DA / P / PCalculator.cpt / CalcDA sources / CalcDA_Arithmetic.c next >
Text File  |  1990-07-06  |  6KB  |  315 lines

  1. /*
  2.  * CalcDA_Arithmetic.c for the Programmer's Calculator project 
  3.  * 
  4.  * Copyright 1990, Peter Ohler 
  5.  * 
  6.  * All Rights Reserved 
  7.  * 
  8.  * The Programmer's Calculator and the source code are shareware.  That means
  9.  * they are not free.  If you use either the source or the calculator then
  10.  * send $5 or $10 (whatever you feel its worth) to the address that follows.
  11.  * The source and calculator can be distributed for free.  Prior to any sale
  12.  * of either the source code or the calculator my permission must be
  13.  * obtained.  This includes sales by shareware distribution houses that sell
  14.  * shareware.  
  15.  * 
  16.  * Peter Ohler 
  17.  * 
  18.  * 3184 Rohrer Drive, Lafayette CA 94549 
  19.  * 
  20.  * (415) 284-7828 
  21.  * 
  22.  * ***************************************************************************
  23.  * 
  24.  * Contains the functions that need two arguments and expect the function
  25.  * designator (*, /, +, -, ...) to be selected between the two arguments.
  26.  * Functions are placed on a stack so that the highest precedence operation
  27.  * is executed first.  For example if the sequence: 2 + 3 * 4 is entered it
  28.  * will be evaluated as 2 + (3 * 4) as convention suggests.  It would not be
  29.  * evaluated in the order entered or as (2 + 3) * 4.  
  30.  */
  31.  
  32. #include "CalcDA.h"
  33.  
  34. /*
  35.  * ***************************************************************************
  36.  * prototypes 
  37.  */
  38. extern void    UpdateXRegText(void);
  39. extern void    UpdateReg2Text(void);
  40. extern IntFunc    PopFuncStack(void);
  41. extern int    PushFuncStack(IntFunc func);
  42. extern void    PopYReg(void);
  43. extern int    PushXonYReg(void);
  44. extern void    FreezeXReg(void);
  45. extern double    Power(double x, double y);
  46.  
  47. int    ChangeSign(void);
  48. int    EvalOrder(IntFunc func);
  49. int    DoArithmetic(IntFunc func);
  50.  
  51. int    DoEqual(void);
  52. int    DoOr(void);
  53. int    DoAnd(void);
  54. int    DoXor(void);
  55. int    DoShiftRight(void);
  56. int    DoShiftLeft(void);
  57. int    DoPlus(void);
  58. int    DoMinus(void);
  59. int    DoMultiply(void);
  60. int    DoDivide(void);
  61. int    DoModulo(void);
  62. int    DoPower(void);
  63. int    DoInvPower(void);
  64.  
  65. /*
  66.  * ***************************************************************************
  67.  * variables 
  68.  */
  69. extern int    exponentActive;
  70. extern int    exponent;
  71.  
  72. /*
  73.  * ***************************************************************************
  74.  * functions 
  75.  */
  76. /*
  77.  * Ok, ok, so this function only takes one argument.  For all the operations
  78.  * functions in this file the x register is updated after the x value is
  79.  * changed.  
  80.  */
  81. int
  82. ChangeSign()
  83. {
  84.     if (INTEGER == typeStack.pos) {
  85.         xReg.value.lv *= -1;
  86.     } else {
  87.         if (exponentActive)
  88.             exponent = -exponent;
  89.         else
  90.             xReg.value.dv *= -1.0;
  91.     }
  92.     UpdateXRegText();
  93.     return 0;
  94. }
  95.  
  96. /*
  97.  * This functions returns the evaluation precedence of a function.  Not real
  98.  * elegant but effective.  
  99.  */
  100. int
  101. EvalOrder(func)
  102.     IntFunc    func;
  103. {
  104.     if (func == DoEqual)
  105.         return 0;
  106.     if (func == DoOr || func == DoAnd || func == DoXor)
  107.         return 1;
  108.     if (func == DoShiftRight || func == DoShiftLeft)
  109.         return 2;
  110.     if (func == DoPlus || func == DoMinus)
  111.         return 3;
  112.     if (func == DoMultiply || func == DoDivide || func == DoModulo)
  113.         return 4;
  114.     if (func == DoPower || func == DoInvPower)
  115.         return 5;
  116.     return -1;
  117. }
  118.  
  119. /*
  120.  * The actual evaluation of the operations entered is done by this function.
  121.  * It will execute any pending operations that have a higher precedence
  122.  * before putting the func on the operations stack (funcPending).  The y
  123.  * register is really a stack for the x values that have been pushed on,
  124.  * awaiting an operation.  
  125.  */
  126. int
  127. DoArithmetic(func)
  128.     IntFunc    func;
  129. {
  130.     IntFunc    topFunc;
  131.     int    order;
  132.     int    ok = 0;
  133.  
  134.     order = EvalOrder(func);
  135.     while (EvalOrder(*funcPending) >= order) {
  136.         if (0L == (topFunc = PopFuncStack()) || (*topFunc)()) {
  137.             SysBeep(1);
  138.         } else {
  139.             /*
  140.              * Assume that the x and y registers were used and
  141.              * the results was put in the x register.  The y
  142.              * register is no longer needed and the value should
  143.              * be popped off.  
  144.              */
  145.             PopYReg();
  146.         }
  147.     }
  148.     if (order > 0) {
  149.         if (PushXonYReg() || PushFuncStack(func))
  150.             ok == -1;
  151.     }
  152.     FreezeXReg();
  153.     UpdateReg2Text();
  154.     return ok;
  155. }
  156.  
  157. /*
  158.  * The equal function doesn't have to do anything.  It is only used to force
  159.  * all pending operations to be executed.  
  160.  */
  161. int
  162. DoEqual()
  163. {
  164.     return 0;
  165. }
  166.  
  167. /*
  168.  * Most of the rest of the functions are similar.  Each peforms some
  169.  * operation on the x and y value and leaves the result in the x register.  
  170.  */
  171. int
  172. DoPlus()
  173. {
  174.     if (INTEGER == typeStack.pos) {
  175.         xReg.value.lv += (*yReg).value.lv;
  176.     } else {
  177.         xReg.value.dv += (*yReg).value.dv;
  178.     }
  179.     return 0;
  180. }
  181.  
  182. int
  183. DoMinus()
  184. {
  185.     if (INTEGER == typeStack.pos) {
  186.         xReg.value.lv = (*yReg).value.lv - xReg.value.lv;
  187.     } else {
  188.         xReg.value.dv = (*yReg).value.dv - xReg.value.dv;
  189.     }
  190.     return 0;
  191. }
  192.  
  193. int
  194. DoMultiply()
  195. {
  196.     if (INTEGER == typeStack.pos) {
  197.         xReg.value.lv *= (*yReg).value.lv;
  198.     } else {
  199.         xReg.value.dv *= (*yReg).value.dv;
  200.     }
  201.     return 0;
  202. }
  203.  
  204. int
  205. DoModulo()
  206. {
  207.     if (INTEGER == typeStack.pos) {
  208.         xReg.value.lv = (*yReg).value.lv % xReg.value.lv;
  209.     } else {
  210.         return -1;
  211.     }
  212.     return 0;
  213. }
  214.  
  215. int
  216. DoDivide()
  217. {
  218.     if (INTEGER == typeStack.pos) {
  219.         xReg.value.lv = (*yReg).value.lv / xReg.value.lv;
  220.     } else {
  221.         xReg.value.dv = (*yReg).value.dv / xReg.value.dv;
  222.     }
  223.     return 0;
  224. }
  225.  
  226. int
  227. DoOr()
  228. {
  229.     if (INTEGER == typeStack.pos) {
  230.         xReg.value.lv |= (*yReg).value.lv;
  231.     } else {
  232.         return -1;
  233.     }
  234.     return 0;
  235. }
  236.  
  237. int
  238. DoAnd()
  239. {
  240.     if (INTEGER == typeStack.pos) {
  241.         xReg.value.lv &= (*yReg).value.lv;
  242.     } else {
  243.         return -1;
  244.     }
  245.     return 0;
  246. }
  247.  
  248. int
  249. DoXor()
  250. {
  251.     if (INTEGER == typeStack.pos) {
  252.         xReg.value.lv ^= (*yReg).value.lv;
  253.     } else {
  254.         return -1;
  255.     }
  256.     return 0;
  257. }
  258.  
  259. int
  260. DoShiftRight()
  261. {
  262.     if (INTEGER == typeStack.pos) {
  263.         xReg.value.lv = (*yReg).value.lv >> xReg.value.lv;
  264.     } else {
  265.         return -1;
  266.     }
  267.     return 0;
  268. }
  269.  
  270. int
  271. DoShiftLeft()
  272. {
  273.     if (INTEGER == typeStack.pos) {
  274.         xReg.value.lv = (*yReg).value.lv << xReg.value.lv;
  275.     } else {
  276.         return -1;
  277.     }
  278.     return 0;
  279. }
  280.  
  281. int
  282. DoPower()
  283. {
  284.     double    x;
  285.  
  286.     if (INTEGER == typeStack.pos) {
  287.         x = Power((double)(*yReg).value.lv, (double)xReg.value.lv);
  288.         if (SIGNED == signStack.pos)
  289.             xReg.value.lv = (long)x;
  290.         else
  291.             xReg.value.lv = (uLong)x;
  292.     } else {
  293.         xReg.value.dv = Power((*yReg).value.dv, xReg.value.dv);
  294.     }
  295.     return 0;
  296. }
  297.  
  298. int
  299. DoInvPower()
  300. {
  301.     double    x;
  302.  
  303.     if (INTEGER == typeStack.pos) {
  304.         x = Power((double)(*yReg).value.lv, 1.0 / (double)xReg.value.lv);
  305.         if (SIGNED == signStack.pos)
  306.             xReg.value.lv = (long)x;
  307.         else
  308.             xReg.value.lv = (uLong)x;
  309.     } else {
  310.         xReg.value.dv = Power((*yReg).value.dv, 1.0 / xReg.value.dv);
  311.     }
  312.     return 0;
  313. }
  314.  
  315.